/**
 * 
 */
package kr.co.insoft.driver.openstack.process;

import java.io.Closeable;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import kr.co.insoft.driver.exception.DriverException;
import kr.co.insoft.driver.exception.ExceptionCode;
import kr.co.insoft.driver.openstack.model.OpenStackCredentialModel;
import kr.co.insoft.driver.openstack.model.OpenStackZoneModel;

import org.jclouds.ContextBuilder;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.domain.Location;
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import com.google.common.collect.ImmutableSet;
import com.google.common.io.Closeables;
import com.google.inject.Module;

/**
 * @author IN-SOFT Inc. skpark@in-soft.co.kr
 * 
 */
public class ZoneProcess implements Closeable {

	private static final Logger logger = LoggerFactory
			.getLogger(ZoneProcess.class);

	private final OpenStackCredentialModel credentialModel;
	private final ComputeService computeService;

	public ZoneProcess(OpenStackCredentialModel credentialModel)
			throws DriverException {
		this.credentialModel = credentialModel;

		try {
			Assert.notNull(this.credentialModel);
			Assert.notNull(this.credentialModel.getEndpoint());
			Assert.notNull(this.credentialModel.getUsername());
			Assert.notNull(this.credentialModel.getAccessKey());
		} catch (IllegalArgumentException e) {
			if (logger.isDebugEnabled()) {
				logger.debug("credentialModel : {}", this.credentialModel);
			}
			throw new DriverException(ExceptionCode.ARGUMENT_ERROR, e);
		}

		try {
			Iterable<Module> modules = ImmutableSet
					.<Module> of(new SLF4JLoggingModule());

			ComputeServiceContext context = ContextBuilder
					.newBuilder(this.credentialModel.getProvider())
					.credentials(this.credentialModel.getUsername(),
							this.credentialModel.getAccessKey())
					.endpoint(this.credentialModel.getEndpoint())
					.modules(modules).buildApi(ComputeServiceContext.class);
			computeService = context.getComputeService();
		} catch (Exception e) {
			throw new DriverException(ExceptionCode.DRIVER_ERROR, e);
		}
	}

	public Set<? extends Location> getZones() throws DriverException {
		try {
			return computeService.listAssignableLocations();
		} catch (Exception e) {
			throw new DriverException(ExceptionCode.DRIVER_ERROR, e);
		}
	}

	public Set<OpenStackZoneModel> getZonesConvertRackSpace()
			throws DriverException {
		Set<OpenStackZoneModel> result = new HashSet<OpenStackZoneModel>();
		for (Location location : getZones()) {
			result.add(new OpenStackZoneModel(location));
		}
		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.io.Closeable#close()
	 */
	public void close() throws IOException {
		Closeables.close(computeService.getContext(), true);
	}
}
